package jp.bgbt.fles.app.wifi;

import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import com.common.utils.LogUtil;
import com.orhanobut.logger.Logger;

import org.greenrobot.eventbus.EventBus;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import jp.bgbt.fles.app.bean.EventMsg;
import jp.bgbt.fles.app.bluetooth.BleDeviceInfo;

public class WifiConnectUtil {
    private final String TAG = getClass().getSimpleName();
    WifiManager wifiManager;
    private Thread connectThread;
    private int netId;
    private WifiInfo mWifiInfo;
    private List<ScanResult> listResult;


    //WIFICIPHER_WEP是WEP ，WIFICIPHER_WPA是WPA，WIFICIPHER_NOPASS没有密码
    public enum WifiCipherType {
        WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID
    }

    // 构造函数
    public WifiConnectUtil(Context context) {
        this.wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        mWifiInfo = wifiManager.getConnectionInfo();
        netId = (mWifiInfo == null) ? 0 : mWifiInfo.getNetworkId();
    }

    // 提供一个外部接口，传入要连接的无线网
    public void connect(String ssid, String password, WifiCipherType type) {
        connectThread = new Thread(new ConnectRunnable(ssid, password, type));
        connectThread.start();
    }

    public void stopConnect() {
        try {
            if (connectThread != null)
                connectThread.interrupt();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到扫描结果 获取无线信号列表
     */
    public ArrayList<ScanResult> getScanResult() {
        // 开始扫描网络
//        scan();
//        wifiManager.startScan()
        listResult = wifiManager.getScanResults();
        ArrayList<ScanResult> list = null;
        if (listResult != null) {
            list = new ArrayList<ScanResult>();
            for (int i = 0; i < listResult.size(); i++) {
//                ScanResult mScanResult = listResult.get(i);
//                Log.e("info", "ssid = " + mScanResult.SSID + "  --level = " + mScanResult.level);
                list.add(listResult.get(i));
            }
        }
        return list;
    }

    // 查看以前是否也配置过这个网络
    private WifiConfiguration isExsits(String SSID) {
        List<WifiConfiguration> existingConfigs = wifiManager
                .getConfiguredNetworks();
        for (WifiConfiguration existingConfig : existingConfigs) {
            if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
                return existingConfig;
            }
        }
        return null;
    }

    private WifiConfiguration createWifiInfo(String SSID, String Password,
                                             WifiCipherType Type) {
        WifiConfiguration config = new WifiConfiguration();
        config.allowedAuthAlgorithms.clear();
        config.priority = 10000;
        config.allowedGroupCiphers.clear();
        config.allowedKeyManagement.clear();
        config.allowedPairwiseCiphers.clear();
        config.allowedProtocols.clear();
        config.priority = 10000;
        config.SSID = "\"" + SSID + "\"";
        // nopass
        if (Type == WifiCipherType.WIFICIPHER_NOPASS) {
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        }
        // wep
        if (Type == WifiCipherType.WIFICIPHER_WEP) {
            if (!TextUtils.isEmpty(Password)) {
                if (isHexWepKey(Password)) {
                    config.wepKeys[0] = Password;
                } else {
                    config.wepKeys[0] = "\"" + Password + "\"";
                }
            }
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            config.wepTxKeyIndex = 0;
        }
        // wpa
        if (Type == WifiCipherType.WIFICIPHER_WPA) {
            config.preSharedKey = "\"" + Password + "\"";
            config.hiddenSSID = true;
            config.allowedAuthAlgorithms
                    .set(WifiConfiguration.AuthAlgorithm.OPEN);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            config.allowedPairwiseCiphers
                    .set(WifiConfiguration.PairwiseCipher.TKIP);
            // 此处需要修改否则不能自动重联
            // config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedPairwiseCiphers
                    .set(WifiConfiguration.PairwiseCipher.CCMP);
            config.status = WifiConfiguration.Status.ENABLED;
        }
        return config;
    }

    // 打开wifi功能
    public boolean shouldOpenWifi() {
        boolean bRet = true;
        if (!wifiManager.isWifiEnabled()) {
            bRet = wifiManager.setWifiEnabled(true);
        }
        return bRet;
    }

    public void startScan() {
        if (wifiManager != null)
            wifiManager.startScan();
    }

    class ConnectRunnable implements Runnable {
        private String ssid;

        private String password;

        private WifiCipherType type;

        public ConnectRunnable(String ssid, String password, WifiCipherType type) {
            this.ssid = ssid;
            this.password = password;
            this.type = type;
        }

        @Override
        public void run() {
            try {
               wifiManager.disconnect();
                if (!wifiManager.isWifiEnabled()) {
                    wifiManager.setWifiEnabled(true);
                    Thread.sleep(1000 * 5);
                }
                if(BleDeviceInfo.getInstance().isDeviceWifiConnected())
                    return;
                // 开启wifi功能需要一段时间(我在手机上测试一般需要1-3秒左右)，所以要等到wifi
                // 状态变成WIFI_STATE_ENABLED的时候才能执行下面的语句
                while (wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING) {
                    try {
                        // 为了避免程序一直while循环，让它睡个100毫秒检测……
                        Thread.sleep(100);
                    } catch (InterruptedException ie) {
                    }
                }
                if(BleDeviceInfo.getInstance().isDeviceWifiConnected())
                    return;
                WifiConfiguration wifiConfig = createWifiInfo(ssid, password, type);
                //
                if (wifiConfig == null) {
                    Log.d(TAG, "wifiConfig is null!");
                    return;
                }

                WifiConfiguration tempConfig = isExsits(ssid);
                int netID = -1;
                if (tempConfig != null) {
                    netID = tempConfig.networkId;
//                    LogUtil.e(ssid + "已存在列表中,移除");
//                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
//                        wifiManager.removeNetwork(tempConfig.networkId);
                } else {
                    netID = wifiManager.addNetwork(wifiConfig);
                }
                Method connectMethod = connectWifiByReflectMethod(netID);
                if (connectMethod == null) {
                    LogUtil.e("连接wifi方式为  enableNetword");
                    boolean enabled = wifiManager.enableNetwork(netID, true);
                    Log.e(TAG, "连接wifi结果" + enabled);
                    if (!enabled) {
                        BleDeviceInfo.getInstance().setConnectingWifi(false);
                        EventBus.getDefault().post(new EventMsg(EventMsg.MSG_AUTO_CONNECT_FAILED));
                        Log.e(TAG, "自动连接wifi失败1");
                        return;
                    }
                }
//
//                if (!BleDeviceInfo.getInstance().isDeviceWifiConnected()) {
//                    LogUtil.e("开始监听连接wifi超时");
//                    EventBus.getDefault().post(new EventMsg(EventMsg.MSG_START_LISTEN_CONNECT_WIFI_STATE));
//                }
//                boolean connected = wifiManager.reconnect();
//                Log.d(TAG, "enableNetwork connected=" + connected);

//                EventBus.getDefault().post(new EventMsg(EventMsg.MSG_DEVICE_WIFI_CONNECTED, null));
            } catch (Exception e) {
                Log.d(TAG, e.getMessage());
                e.printStackTrace();
                BleDeviceInfo.getInstance().setConnectingWifi(false);
                EventBus.getDefault().post(new EventMsg(EventMsg.MSG_AUTO_CONNECT_FAILED));
                Log.e(TAG, "自动连接wifi失败2");
            }
        }
    }

    private static boolean isHexWepKey(String wepKey) {
        final int len = wepKey.length();

        // WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)
        if (len != 10 && len != 26 && len != 58) {
            return false;
        }

        return isHex(wepKey);
    }

    private static boolean isHex(String key) {
        for (int i = key.length() - 1; i >= 0; i--) {
            final char c = key.charAt(i);
            if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a'
                    && c <= 'f')) {
                return false;
            }
        }

        return true;
    }

    public boolean wifiEnable() {
        if (!wifiManager.isWifiEnabled()) {
            wifiManager.setWifiEnabled(true);
            return false;
        }
        return true;
    }

    public String getConnectedWifiSSID() {
        mWifiInfo = wifiManager.getConnectionInfo();
        return mWifiInfo != null ? mWifiInfo.getSSID() : "";
    }

    private Method connectWifiByReflectMethod(int netId) {
        Method connectMethod = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Logger.i(TAG, "connectWifiByReflectMethod road 1");
            // 反射方法： connect(int, listener) , 4.2 <= phone's android version
            for (Method methodSub : wifiManager.getClass()
                    .getDeclaredMethods()) {
                if ("connect".equalsIgnoreCase(methodSub.getName())) {
                    Class<?>[] types = methodSub.getParameterTypes();
                    if (types != null && types.length > 0) {
                        if ("int".equalsIgnoreCase(types[0].getName())) {
                            connectMethod = methodSub;
                        }
                    }
                }
            }
            if (connectMethod != null) {
                try {
                    connectMethod.invoke(wifiManager, netId, null);
                } catch (Exception e) {
                    e.printStackTrace();
                    BleDeviceInfo.getInstance().setConnectingWifi(false);
                    EventBus.getDefault().post(new EventMsg(EventMsg.MSG_AUTO_CONNECT_FAILED));
                    Log.e(TAG, "自动连接wifi失败3");
                    LogUtil.d("connectWifiByReflectMethod Android " + Build.VERSION.SDK_INT + " error!");
                    return null;
                }
            }
        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {
            // 反射方法: connect(Channel c, int networkId, ActionListener listener)
            // 暂时不处理4.1的情况 , 4.1 == phone's android version
            Logger.i(TAG, "connectWifiByReflectMethod road 2");
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH
                && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            Logger.i(TAG, "connectWifiByReflectMethod road 3");
            // 反射方法：connectNetwork(int networkId) ,
            // 4.0 <= phone's android version < 4.1
            for (Method methodSub : wifiManager.getClass()
                    .getDeclaredMethods()) {
                if ("connectNetwork".equalsIgnoreCase(methodSub.getName())) {
                    Class<?>[] types = methodSub.getParameterTypes();
                    if (types != null && types.length > 0) {
                        if ("int".equalsIgnoreCase(types[0].getName())) {
                            connectMethod = methodSub;
                        }
                    }
                }
            }
            if (connectMethod != null) {
                try {
                    connectMethod.invoke(wifiManager, netId);
                } catch (Exception e) {
                    e.printStackTrace();
                    Logger.i(TAG, "connectWifiByReflectMethod Android "
                            + Build.VERSION.SDK_INT + " error!");
                    return null;
                }
            }
        } else {
            // < android 4.0
            return null;
        }
        return connectMethod;
    }
}
